﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using Abp.Dependency;
using Abp.Runtime.Security;

namespace AbpProjectTemplate.Web.Authentication.JwtBearer
{
    public class JwtHepler : ISingletonDependency
    {
        public readonly JwtAuthOptions Options;
        public JwtHepler(JwtAuthOptions options)
        {
            this.Options = options;
        }

        /// <summary>
        /// 生成identity的jwt claims
        /// </summary>
        /// <param name="identity"></param>
        /// <returns></returns>
        public List<Claim> CreateClaims(ClaimsIdentity identity)
        {
            var claims = identity.Claims.ToList();
            var nameIdClaim = claims.First(c => c.Type == ClaimTypes.NameIdentifier);

            // Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
            claims.AddRange(new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, nameIdClaim.Value),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
            });

            return claims;
        }

        /// <summary>
        /// 创建token
        /// </summary>
        /// <param name="claims"></param>
        /// <param name="expiration"></param>
        /// <returns></returns>
        public string CreateAccessToken(IEnumerable<Claim> claims, TimeSpan? expiration = null)
        {
            var now = DateTime.UtcNow;

            var jwtSecurityToken = new JwtSecurityToken(
                issuer: this.Options.Issuer,
                audience: this.Options.Audience,
                claims: claims,
                notBefore: now,
                expires: now.Add(expiration ?? this.Options.Expiration),
                signingCredentials: this.Options.SigningCredentials
            );

            return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
        }

        /// <summary>
        /// 根据identity生成jwt token
        /// </summary>
        /// <param name="identity"></param>
        /// <param name="expiration"></param>
        /// <returns></returns>
        public string CreateAccessToken(ClaimsIdentity identity, TimeSpan? expiration = null)
        {
            var claims = this.CreateClaims(identity);
            return this.CreateAccessToken(claims, expiration);
        }

        /// <summary>
        /// 加密token
        /// </summary>
        /// <param name="accessToken"></param>
        /// <returns></returns>
        public string EncryptAccessToken(string accessToken)
        {
            return SimpleStringCipher.Instance.Encrypt(accessToken, AppConsts.DefaultPassPhrase);
        }
    }
}

